package com.api.syh56.shengyunhui.websocket;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import jakarta.servlet.http.HttpSession;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;


import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Slf4j
@Component
@ServerEndpoint(value = "/chatServer/{userId}")
public class ChatServer {
    private static int onlineCount = 0; //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static CopyOnWriteArraySet<ChatServer> webSocketSet = new CopyOnWriteArraySet<ChatServer>();
    private Session session;    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private String userId;      //用户名
    private HttpSession httpSession;    //request的session

//    private static List list = new ArrayList<>();   //在线列表,记录用户名称
    private static HashSet<String> list = new HashSet<>();   //在线列表,记录用户名称
    private static Map<String,Object> routetab = new HashMap<>();  //用户名和websocket的session绑定的路由表

//    private static ConcurrentHashMap<String,ConcurrentHashMap<String,Object>> routetab = new ConcurrentHashMap<>();  //用户名和websocket的session绑定的路由表
    /**
     * 连接建立成功调用的方法
     * @param session  可选的参数。session为与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(@PathParam("userId")String userId, Session session){

        // 处理新连接
        log.info(userId + "建立新连接");
        this.session = session;
        webSocketSet.add(this);     //加入set中

//        this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
//        this.userId=(String) httpSession.getAttribute("userid");    //获取当前用户
        //获取当前登录用户的id
        this.userId = userId;
        list.add(userId);           //将用户名加入在线列表
        routetab.put(userId, session);   //将用户名和session绑定到路由表

//        String[] parts = userId.split(",");
//        String uId = parts[0];
//        String deviceId = parts[1];
//        if (routetab.containsKey(uId)) {
//            ConcurrentHashMap<String, Object> stringObjectMap = routetab.get(uId);
//            stringObjectMap.put(deviceId, session);
//
//        }else {
//            ConcurrentHashMap<String, Object> deviceToSession = new ConcurrentHashMap<>();
//            deviceToSession.put(deviceId, session);
//            routetab.put(uId, deviceToSession);
//        }


        updateOnlineCount();           //在线数加1;

        log.info(userId + "加入聊天室,当前在线人数为"+getOnlineCount()+"位");
        String message = getMessage("[" + userId + "]加入聊天室,当前在线人数为"+getOnlineCount()+"位", "notice",  list);
        log.info(message);
//        broadcast("");         //广播
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(){
        webSocketSet.remove(this);  //从set中删除

        list.remove(userId);        //从在线列表移除这个用户
        routetab.remove(userId);
        updateOnlineCount();           //在线数减1
        String message = getMessage("[" + userId +"]离开了聊天室,当前在线人数为"+getOnlineCount()+"位", "notice", list);
        log.info(message);
//        broadcast("");         //广播
    }

    /**
     * 接收客户端的message,判断是否有接收人而选择进行广播还是指定发送
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message) {
        for (ChatServer item : webSocketSet){
            try {
                item.sendMessage(message);
            }catch (IOException e){
                log.error("发送消息失败",e);
            }
        }
//        JSONObject chat = JSON.parseObject(_message);
//        JSONObject message = JSON.parseObject(chat.get("message").toString());
//        if(message.get("to") == null || message.get("to").equals("")){      //如果to为空,则广播;如果不为空,则对指定的用户发送消息
//            broadcast(_message);
//        }else{
//            String [] userlist = message.get("to").toString().split(",");
//            singleSend(_message, (Session) routetab.get(message.get("from")));      //发送给自己
//            for(String user : userlist){
//                if(!user.equals(message.get("from"))){
//                    singleSend(_message, (Session) routetab.get(user));     //分别发送给每个指定用户
//                }
//            }
//        }
        //发送同样的消息返给该客户端
//        try {
//            session.getBasicRemote().sendText(_message);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
    }

    public void sendMessage(String message) throws IOException{
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 发生错误时调用
     * @param error
     */
    @OnError
    public void onError(Throwable error){
        error.printStackTrace();
    }

    /**
     * 广播消息
     * @param message
     */
    public void broadcast(String message){
        for(ChatServer chat: webSocketSet){
            try {
                synchronized (chat){
                    chat.session.getBasicRemote().sendText(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
                continue;
            }
        }
    }

    /**
     * 对特定用户发送消息
     * @param message
     * @param session
     */
    public void singleSend(String message, Session session){
        try {
            session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 组装返回给前台的消息
     * @param message   交互信息
     * @param type      信息类型
     * @param list      在线列表
     * @return
     */
    public String getMessage(String message, String type, HashSet<String> list){
        JSONObject member = new JSONObject();
        member.put("message", message);
        member.put("type", type);
        member.put("list", list);
        return member.toString();
    }

    public  int getOnlineCount() {
        return onlineCount;
    }

    public  void addOnlineCount() {
        ChatServer.onlineCount++;
    }

    public  void subOnlineCount() {
        ChatServer.onlineCount--;
    }

    public  void updateOnlineCount() {
        onlineCount = list.size();
    }

    public HashSet<String>  getList() {
        return list;
    }

    public Map getRoutetab() {
        return routetab;
    }


    /**
     * 发送给指定userId(省运慧系统)
     * @param userId
     * @param message
     */
    public void sendToUser(Long userId, String message) {

        // 遍历routetab，找到匹配userId的所有sessions
        for (Map.Entry<String,Object> entry : routetab.entrySet()) {
            String key = entry.getKey();
            System.out.println("key:" + key);
            Long currentUserId = null;
            if (key.contains(",")){
                currentUserId = extractUserId(key); // 假设这个方法能从键中提取userId
            }else {
                currentUserId = Long.parseLong(key);
            }
            if (currentUserId != null && currentUserId.equals(userId)) {
                try {
                    // 使用getBasicRemote().sendText()方法发送消息
                    Session value = (Session) entry.getValue();
                    value.getBasicRemote().sendText(message);
                    // 打印消息
                    log.info("发送给websocket用户：" + key + "的消息是：" + message);
                } catch (IOException e) {
                    e.printStackTrace();
                    // 处理异常，例如打印错误信息或从路由表中移除无效的Session
                }
            } else {
                // 如果没有找到Session，可以记录日志或进行其他处理
                log.info("websocket用户：" + key + "不需要发送");
            }
        }

//        // 从路由表中获取指定用户的Session
//        Session userSession = (Session) routetab.get(Long.toString(userId));
//        if (userSession != null) {
//            try {
//                // 使用getBasicRemote().sendText()方法发送消息
//                userSession.getBasicRemote().sendText(message);
//                // 打印消息
//                log.info("发送给websocket用户：" + userId + "的消息是：" + message);
//            } catch (IOException e) {
//                e.printStackTrace();
//                // 处理异常，例如打印错误信息或从路由表中移除无效的Session
//            }
//        } else {
//            // 如果没有找到Session，可以记录日志或进行其他处理
//            log.info("websocket用户：" + userId + "未上线");
//        }
    }

    // 辅助方法，用于从键中提取userId
    private Long extractUserId(String key) {
        String[] parts = key.split(",");
        if (parts.length > 0) {
            try {
                return Long.parseLong(parts[0]);
            } catch (NumberFormatException e) {
                log.error("提取userId失败", e);
            }
        }
        return null;
    }



}